/*
 * CaracteresHandler.cpp
 *
 *  Created on: 26/11/2011
 *      Author: putaro
 */

#include "CaracteresHandler.h"
#include <cstring>
#include <string>
#include <iostream>
#include <stdlib.h>

/*
 * Pre:-
 * Post: Se agregado un nuevo caracter al string correspondiente.
 * La codificación del caracter de entrada debe ser en UTF-8, de manera tal que
 * si se prensetase un caracter de más de un byte este método recuperará los
 * caracteres necesarios del archivo de entrada.
 * Los carácteres castellanos acentuados, con dierisis o en minúscula, se convierten
 * a sus respectivas mayúsculas sin acentuar.
 * Un carácter UTF8 puede implicar que se guarde en termino varios tipos de datos
 * char.
 * Para los carácteres de más de un byte el término no coincirá con su equivalente UTF8
 * sino que será una codificación propia de este programa.
 * Returns: True si el carácter es válido para formar parte de un término.
*/
bool CaracteresHandler::procesarCaracter(const char caracter , bool & isNumerico ,
										string & termino , AsistenteObtencionDeTerminos &asistente,
										ifstream & archivo){
	bool retorno = false;
	if(caracter >= 0){
		if((caracter>='A')&&(caracter<='Z')){
			isNumerico = false;
			retorno = true;
			termino+=(char)caracter;
		}else{
			if((caracter>='a')&&(caracter<='z')){
				isNumerico = false;
				retorno = true;
				termino+=toupper((char)caracter);
			} else{
				if((caracter>='0')&&(caracter<='9')){
					isNumerico = true;
					retorno = true;
					termino+=caracter;
				}else{
					isNumerico = false;
					switch (caracter) {
						case '@':   termino+=(char)caracter;
									retorno = true;
									break;
						case '_':   termino+=caracter;
									retorno = true;
									break;
					}
				}
			}
		}
	}else{
		isNumerico = false;
		retorno = procesarUTF(caracter,isNumerico,termino,asistente,archivo);
	}
	return retorno;
}

/*
 * Pre:
 * Post: Se ha procesado un caracter en UTF8 comprobando si corresponde a dicho tipo
 * de formato.
*/
bool CaracteresHandler::procesarUTF(const char caracter , bool & isNumerico ,
									string & termino , AsistenteObtencionDeTerminos &asistente,
									ifstream & archivo){
	bool retorno = false;
	int desplazamiento = 6;
	bool fin = false;
	//localizacion del primer cero
	while((!fin) &&(desplazamiento > 4) ){
		if(((caracter>>desplazamiento)&1) == 0){
			fin = true;
		} else{
			desplazamiento--;
		}
	}
	if(desplazamiento >= 0){
		retorno = procesarUTF8(caracter,isNumerico,termino,asistente,archivo);
	}else{
		cout<<" -> ERROR: Formato no soportado";
	}
	return retorno;
}

/*
 * Pre:-
 * Post: Se ha procesado un caracter en UTF8.
*/
bool CaracteresHandler::procesarUTF8(const char caracter , bool & isNumerico ,
									string & termino , AsistenteObtencionDeTerminos &asistente,
									ifstream & archivo){
	unsigned int cantidadBytes = 0;
	int desplazamiento = 5;
	bool fin = false;
	//localizacion del primer cero
	while((!fin) &&(desplazamiento > 0) ){
		if(((caracter>>desplazamiento)&1) == 0){
			fin = true;
		} else{
			desplazamiento--;
		}
	}
	cantidadBytes = 7-desplazamiento;
	if(cantidadBytes == 2){
		termino+=(caracter & 127);
		char caracterAux = 0;
		asistente.leerCaracter(archivo,caracterAux);
		convertirCaracter(caracterAux,termino);
	}else{
		termino+=(caracter & 127);
		while(cantidadBytes > 0){
			char caracterAux = 0;
			asistente.leerCaracter(archivo,caracterAux);
			termino+=(caracterAux&127);
			cantidadBytes--;
		}
	}
	return true;
}

/*
 * Pre:-
 * Post: Se ha convertido el caracter según corresponda.
*/
void CaracteresHandler::convertirCaracter(const char caracter , string & termino){
	switch (caracter){
		case -92 :
		case -95 :
		case -96 :
		case -124 :
		case -127 :
		case -128 :	termino+='A';
					break;
		case -85 :
		case -87 :
		case -88 :
		case -117 :
		case -119 :
		case -120 : termino+='E';
					break;
		case -81 :
		case -83 :
		case -84 :
		case -113 :
		case -115 :
		case -116 :	termino+='I';
					break;
		case -74 :
		case -77 :
		case -78 :
		case -106 :
		case -109 :
		case -110 :	termino+='O';
					break;
		case -70 :
		case -68 :
		case -71 :
		case -100 :
		case -102 :
		case -103 :	termino+='U';
					break;
		case -79 :
		case -111 :	termino+='N';
					break;
	}
}
